package gov.child.dao.impl;

import gov.child.dao.AbstractDao;
import gov.child.dao.GuideDao;
import gov.child.dao.exception.*;
import gov.child.entities.po.EDepartment;
import gov.child.entities.po.EGuide;
import gov.child.entities.vo.Page;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.stream.Collectors;

/**
 * The type Guide dao. --finish
 *
 * @author fzh
 * @since 2017 /9/10
 */
@Repository("guideDao")
public class GuideDaoImpl extends AbstractDao implements GuideDao {

    @Override
    public List find(EDepartment department, Boolean online, Byte... obj) {
        Session session = currentSession();
        Query query;
        String hql;
        if (online) {
            hql = "from EGuide where deptP = :deptP and online = :online order by createTime";
            query = session.createQuery(hql)
                    .setParameter("deptP",department.getId())
                    .setParameter("online", online);
        } else {
            hql = "from EGuide where deptP = :deptP order by createTime";
            query = session.createQuery(hql)
                    .setParameter("deptP",department.getId());
        }

        List r = query.list();
        r = (List) r.stream().filter(guide -> {
            EGuide g = (EGuide) guide;
            boolean f = false;
            for (Byte b : obj) {
                f = f || b.equals(g.getObj());
            }
            return f;
        }).collect(Collectors.toList());
        return r;
    }

    @Override
    public List findAll(Page page) throws EntityQueryException {
        Session session = currentSession();
        String hql = "from EGuide order by createTime";
        Query query = session.createQuery(hql);
        return doPaginate(query, page);
    }

    @Override
    public EGuide findById(Integer id) throws EntityQueryException {
        Session session = currentSession();
        String hql = "from EGuide where id = :id order by createTime";
        return (EGuide) session.createQuery(hql).setParameter("id", id).uniqueResult();
    }

    @Override
    public List findByDepartmentId(Integer departmentId, Page page) {
        Session session = currentSession();
        String hql = "from EGuide where deptP = :did order by createTime";
        Query query = session.createQuery(hql).setParameter("did", departmentId);
        return doPaginate(query, page);
    }

    @Override
    public EGuide findByGuideCode(String code) {
        Session session = currentSession();
        String hql = "from EGuide where guideCode = :code order by createTime";
        return (EGuide) session.createQuery(hql).setParameter("code", code).uniqueResult();
    }

    @Override
    public List findByObj(Byte obj, Page page) throws EntityQueryException {
        Session session = currentSession();
        String hql = "from EGuide where obj = :obj order by createTime";
        Query query = session.createQuery(hql).setParameter("obj", obj);
        return doPaginate(query, page);
    }

    @Override
    public List findByOnline(Byte online, Page page) throws EntityQueryException {
        Session session = currentSession();
        String hql = "from EGuide where online = :ol order by createTime";
        Query query = session.createQuery(hql).setParameter("ol", online);
        return doPaginate(query, page);
    }

    @Override
    public void save(EGuide guide) throws EntitySaveException {
        try {
            currentSession().save(guide);
        } catch (DataAccessResourceFailureException e) {
            logger.error("GuideDao save exception: " + e.getMessage());
            throw new EntitySaveException("GuideDao save exception " + e);
        }
    }

    @Override
    public void delete(EGuide guide) throws EntityDeleteException {
        try {
            currentSession().delete(guide);
        } catch (DataAccessResourceFailureException e) {
            logger.error(GuideDao.class.getSimpleName()+ " delete exception "+ e);
            throw new EntityDeleteException(GuideDao.class.getSimpleName()+ " delete exception "+ e);
        }
    }

    @Override
    public void update(EGuide guide) throws EntityUpdateException {
        // TODO maybe need optimization
        try {
            currentSession().update(guide);
        } catch (DataAccessResourceFailureException e) {
            logger.error(GuideDao.class.getSimpleName()+ " update exception "+ e);
            throw new EntityUpdateException(GuideDao.class.getSimpleName()+ " update exception "+ e);
        }
    }

    @Override
    public Long total() throws PageInitialException {
        Session session = currentSession();
        String hql = "select count (*) from EGuide";
        return (Long) session.createQuery(hql).uniqueResult();
    }
}
